package com.dx.financehy.modules.security.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.dx.financehy.modules.security.entity.dto.SmsAuthDTO;
import com.dx.financehy.modules.security.entity.dto.WxAuthDTO;
import com.dx.financehy.modules.security.service.AuthService;
import com.dx.financehy.modules.system.domain.User;
import com.dx.financehy.modules.system.service.UserService;
import com.dx.financehy.utils.MyUtil;
import com.dx.financehy.utils.SpringContextHolder;
import com.dx.financehy.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

/**
 * <pre>
 * @描述： 认证
 * @作者：CLD
 * @创建时间：2022-03-22 15:55
 * </pre>
 **/
@RequiredArgsConstructor
@Service
@Slf4j
public class AuthServiceImpl implements AuthService {

    private final UserService userService;
    private final PasswordEncoder passwordEncoder;

    @Override
    public User wxlogin(WxAuthDTO wxAuthDTO) throws WxErrorException {
        WxMaService wxMaServiceBean = SpringContextHolder.getBean(WxMaService.class);
        WxMaService wxMaService = wxMaServiceBean.switchoverTo(wxAuthDTO.getAppId());

        WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(wxAuthDTO.getCode());
        String sessionKey = sessionInfo.getSessionKey();

        WxMaPhoneNumberInfo phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(
                sessionKey, wxAuthDTO.getEncryptedData(), wxAuthDTO.getIv());

        String phone = phoneNoInfo.getPhoneNumber();
        return checkUser(sessionInfo, phone,wxAuthDTO.getMerchantId());
    }

    @Override
    public User wxOpenIdLogin(WxAuthDTO wxAuthDTO) throws WxErrorException {
        WxMaService wxMaServiceBean = SpringContextHolder.getBean(WxMaService.class);
        WxMaService wxMaService = wxMaServiceBean.switchoverTo(wxAuthDTO.getAppId());

        WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(wxAuthDTO.getCode());

        // ✅ 不再获取手机号信息
        return checkOpenIdUser(sessionInfo, null, wxAuthDTO.getMerchantId());
    }

    @Override
    public User weChatlogin(WxAuthDTO wxAuthDTO) throws WxErrorException {
        WxMaService wxMaServiceBean = SpringContextHolder.getBean(WxMaService.class);
        WxMaService wxMaService = wxMaServiceBean.switchoverTo(wxAuthDTO.getAppId());

        WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(wxAuthDTO.getCode());
        /*String sessionKey = sessionInfo.getSessionKey();

        WxMaPhoneNumberInfo phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(
                sessionKey, wxAuthDTO.getEncryptedData(), wxAuthDTO.getIv());

        String phone = phoneNoInfo.getPhoneNumber();*/
        return checkNopwUser(sessionInfo);
    }

    @Override
    public User smslogin(SmsAuthDTO smsAuthDTO) {
        String phone = smsAuthDTO.getPhone();
        return checkUser(null, phone,null);
    }

    /**
     * 检查用户，如果用户不存在，则保存
     *
     * @param sessionInfo
     * @param phone
     * @return
     */
    private User checkUser(WxMaJscode2SessionResult sessionInfo, String phone,String merchantId) {
        User user = userService.getByUsername(phone);
        if (user == null) {
            // 保存用户信息
            user = User.builder()
                    .username(phone)
                    .name("wm_" + phone.substring(7))
                    .wxOpenId(sessionInfo.getOpenid())
                    .userType(3)
                    .merchantId(merchantId)
                    .isLogin(true)
                    .password(passwordEncoder.encode(MyUtil.generatePassword(8)))
                    .enabled(true).build();
            userService.save(user);
        } else {
            if (StringUtils.isBlank(user.getMerchantId()) && StringUtils.isNotBlank(merchantId)){
                user.setMerchantId(merchantId);
            }
            userService.updateById(user);
        }
        return user;
    }

    /**
     * 检查用户，如果用户不存在，则保存
     *
     * @param sessionInfo
     * @param phone
     * @return
     */
    private User checkOpenIdUser(WxMaJscode2SessionResult sessionInfo, String phone,String merchantId) {
        User user = userService.getByOpenId(sessionInfo.getOpenid());
        if (user == null) {
            // 从数据库获取当前最大序号
            Integer maxIndex = userService.getMaxVisitorIndex();
            int nextIndex = (maxIndex == null ? 0 : maxIndex) + 1;

            String username = "游客" + nextIndex;
            // ✅ 可以不传手机号，直接使用 openId 构造用户名
            //String username = "wx_" + sessionInfo.getOpenid().substring(0, 8); // 示例用户名生成方式
            user = User.builder()
                    .visitorIndex(nextIndex)
                    .username(username)
                    .name("游客" + nextIndex)
                    .wxOpenId(sessionInfo.getOpenid())
                    .userType(3)
                    .merchantId(merchantId)
                    .isLogin(true)
                    /*.password(passwordEncoder.encode(MyUtil.generatePassword(8)))*/
                    .password(passwordEncoder.encode("siyu_password"))
                    .enabled(true).build();
            userService.save(user);
        } else {
            if (StringUtils.isBlank(user.getMerchantId()) && StringUtils.isNotBlank(merchantId)){
                user.setMerchantId(merchantId);
            }
            userService.updateById(user);
        }
        return user;
    }

    /**
     * 检查用户，如果用户不存在，则保存
     *
     * @param sessionInfo
     * @return
     */
    private User checkNopwUser(WxMaJscode2SessionResult sessionInfo) {
        User user = userService.getByUsername("wmNopUname" + sessionInfo.getOpenid());
        if (user == null) {
            // 保存用户信息
            user = User.builder()
                    .username("wmNopUname" + sessionInfo.getOpenid())
                    .wxOpenId("Nophone" + sessionInfo.getOpenid())
                    .name("Noname" + "免密用户")
                    .userType(3)
                    .isLogin(true)
                    .password(passwordEncoder.encode(MyUtil.generatePassword(8)))
                    .enabled(true).build();
            userService.save(user);
        } else {
            userService.updateById(user);
        }
        return user;
    }

}
